package com.arsn.myf.flow.service.impl;

import com.arsn.myf.common.util.StringUtils;
import com.arsn.myf.flow.entity.Flow;
import com.arsn.myf.flow.entity.FlowModel;
import com.arsn.myf.flow.mapper.FlowMapper;
import com.arsn.myf.flow.service.FlowEngineService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.ui.modeler.domain.Model;
import org.flowable.ui.modeler.serviceapi.ModelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * flowEngine 服务实现层
 *
 * @author zhongrj
 * @since 2022-10-18
 */
@Service
public class FlowEngineServiceImpl extends ServiceImpl<FlowMapper, FlowModel> implements FlowEngineService {

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private ModelService modelService;
    /**
     * 分页
     *
     * @param flow flow 实体
     * @param page page 对象
     */
    @Override
    public IPage<FlowModel> selectPageDeptList(Page<FlowModel> page, FlowModel flow) {
        return page.setRecords(baseMapper.selectFlowPage(page, flow));
    }

    /**
     * 部署模型
     * @param flow
     */
    @Override
    public boolean deployModel(FlowModel flow) {
        boolean flag = false;
        //查询模型信息
        Model model = modelService.getModel(flow.getId());
        BpmnModel bpmnModel = modelService.getBpmnModel(model);
        //部署流程
        Deployment deployment = repositoryService.createDeployment()
                .name(model.getName())
                .addBpmnModel(model.getName() + ".bpmn20.xml", bpmnModel)
                .deploy();
        flag = deployment == null ? true : false;
        //返回
        return flag;
    }

    /**
     * 获取流程节点图--返回xml数据*（前端bpmn.js解析）
     *
     * @param processDefinitionId 流程定义id
     * @param processInstanceId   流程实例id
     * @return
     */
    @Override
    public Map<String, Object> processView(String processDefinitionId, String processInstanceId) {
        Map<String, Object> map = new HashMap<>(2);
        List<Flow> list = new ArrayList<>();
        if (!StringUtils.isBlank(processInstanceId)) {
            //获取历史流程实例信息
            HistoricProcessInstance historicProcessInstance
                    = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            processDefinitionId = historicProcessInstance.getProcessDefinitionId();
            //设置已流过的节点
            list = historyFlowList(processInstanceId);
        }
        map.put("flow", list);

        //查询 bpmnModel信息
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        //获取流程图
        map.put("xml", new String(new BpmnXMLConverter().convertToXML(bpmnModel)));
        //返回
        return map;
    }

    /**
     * 已流过的节点集合
     *
     * @param processInstanceId 流程实例id
     * @return
     */
    private List<Flow> historyFlowList(String processInstanceId) {
        List<Flow> list = new ArrayList<>();
        List<HistoricActivityInstance> historicActivityInstanceList
                = historyService.createHistoricActivityInstanceQuery().
                processInstanceId(processInstanceId).
                orderByHistoricActivityInstanceStartTime().asc().orderByHistoricActivityInstanceEndTime().asc().list();
        historicActivityInstanceList.forEach(historicActivityInstance -> {
            Flow flow = new Flow();
            flow.setHistoryActivityId(historicActivityInstance.getActivityId());
            flow.setHistoryActivityName(historicActivityInstance.getActivityName());
            list.add(flow);
        });
        //返回
        return list;
    }
}
